[LeetCode] 496. Next Greater Element I 下一个较大的元素之一

 

You are given two integer arrays nums1 and nums2 both of unique elements, where nums1 is a subset of nums2.

Find all the next greater numbers for nums1's elements in the corresponding places of nums2.

The Next Greater Number of a number x in nums1 is the first greater number to its right in nums2. If it does not exist, return -1 for this number.

 

Example 1:

Input: nums1 = [4,1,2], nums2 = [1,3,4,2]
Output: [-1,3,-1]
Explanation:
For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1.
For number 1 in the first array, the next greater number for it in the second array is 3.
For number 2 in the first array, there is no next greater number for it in the second array, so output -1.

Example 2:

Input: nums1 = [2,4], nums2 = [1,2,3,4]
Output: [3,-1]
Explanation:
For number 2 in the first array, the next greater number for it in the second array is 3.
For number 4 in the first array, there is no next greater number for it in the second array, so output -1.

 

Constraints:

  • 1 <= nums1.length <= nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 104
  • All integers in nums1 and nums2 are unique.
  • All the integers of nums1 also appear in nums2.

 

Follow up: Could you find an O(nums1.length + nums2.length) solution?

 

这道题给了一个数组,又给了该数组的一个子集合,让我们求集合中每个数字在原数组中右边第一个较大的数字。参考题目中给的例子,题意不难理解,既然这次难度标识为 Easy,想必不是一道太难的题。二话不说,先上无脑暴力搜索,遍历子集合中的每一个数字,然后在原数组中找到这个数字,然后向右遍历,找到第一个大于该数字的数即可,参见代码如下:

 

解法一:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
        vector<int> res(findNums.size());
        for (int i = 0; i < findNums.size(); ++i) {
            int j = 0, k = 0;
            for (; j < nums.size(); ++j) {
                if (nums[j] == findNums[i]) break;
            }
            for (k = j + 1; k < nums.size(); ++k) {
                if (nums[k] > nums[j]) {
                    res[i] = nums[k];
                    break;
                }
            }
            if (k == nums.size()) res[i] = -1;
        }
        return res;
    }
};

 

我们来对上面的方法稍做优化,用 HashMap 先来建立每个数字和其坐标位置之间的映射,那么在遍历子集合中的数字时,就能直接定位到该数字在原数组中的位置,然后再往右边遍历寻找较大数即可,参见代码如下:

 

解法二:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
        vector<int> res(findNums.size());
        unordered_map<int, int> m;
        for (int i = 0; i < nums.size(); ++i) {
            m[nums[i]] = i;
        }
        for (int i = 0; i < findNums.size(); ++i) {
            res[i] = -1;
            int start = m[findNums[i]];
            for (int j = start + 1; j < nums.size(); ++j) {
                if (nums[j] > findNums[i]) {
                    res[i] = nums[j];
                    break;
                }
            }
        }
        return res;
    }
};

 

下面这种方法使用了 HashMap 和栈,但是这里的 HashMap 和上面的不一样,这里是建立每个数字和其右边第一个较大数之间的映射,没有的话就是 -1。遍历原数组中的所有数字,如果此时栈不为空,且栈顶元素小于当前数字,说明当前数字就是栈顶元素的右边第一个较大数,那么建立二者的映射,并且去除当前栈顶元素,最后将当前遍历到的数字压入栈。当所有数字都建立了映射,那么最后可以直接通过 HashMap 快速的找到子集合中数字的右边较大值,参见代码如下:

 

解法三:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
        vector<int> res;
        stack<int> st;
        unordered_map<int, int> m;
        for (int num : nums) {
            while (!st.empty() && st.top() < num) {
                m[st.top()] = num; st.pop();
            }
            st.push(num);
        }
        for (int num : findNums) {
            res.push_back(m.count(num) ? m[num] : -1);
        }        
        return res;
    }
};

 

类似题目:

Next Greater Element II

Next Greater Element III

Daily Temperatures

 

参考资料:

https://leetcode.com/problems/next-greater-element-i

https://leetcode.com/problems/next-greater-element-i/discuss/97676/java-solution-with-hashmap

https://leetcode.com/problems/next-greater-element-i/discuss/97595/java-10-lines-linear-time-complexity-on-with-explanation

 

LeetCode All in One 题目讲解汇总(持续更新中...)

posted @ 2017-02-15 03:15  Grandyang  阅读(17155)  评论(5编辑  收藏  举报
Fork me on GitHub